const dayjs = require('dayjs');
/**
 * 缓存管理器工厂
 * 为每个模块创建独立的缓存管理器实例
 */

import { CACHE_PREFIX, DEFAULT_EXPIRE_TIME } from './cache.js';
import cacheHelper from '../../helpers/cache_helper.js';

/**
 * 创建模块专用的缓存管理器
 * @param {String} moduleName 模块名称
 * @param {Object} options 缓存选项
 * @return {Object} 缓存管理器实例
 */
export function createCacheManager(moduleName, options = {}) {
  if (!moduleName) {
    throw new Error('缓存管理器必须指定模块名称');
  }
  
  // 默认选项
  const defaultOptions = {
    expireTime: DEFAULT_EXPIRE_TIME,
    cleanupInterval: 60 * 60 * 1000, // 1小时清理间隔
    autoRefresh: false,
    prefix: `${moduleName.toUpperCase()}_`,
    debug: false
  };
  
  // 合并选项
  const cacheOptions = { ...defaultOptions, ...options };
  
  // 模块前缀
  const modulePrefix = `${CACHE_PREFIX}${cacheOptions.prefix}`;
  
  // 清理定时器
  let cleanupTimer = null;
  
  // 刷新定时器集合
  const refreshTimers = {};
  
  // 缓存管理器实例
  const cacheManager = {
    // 配置
    options: cacheOptions,
    
    // 统计信息
    stats: {
      hitCount: 0,
      missCount: 0,
      setCount: 0,
      removeCount: 0,
      lastCleanTime: null
    },
    
    /**
     * 设置缓存
     * @param {String} key 缓存键
     * @param {Object} data 要缓存的数据
     * @param {Number} expireTime 过期时间（毫秒）
     * @param {Boolean} autoRefresh 是否自动刷新
     * @param {Function} refreshCallback 刷新回调函数
     * @return {Boolean} 操作结果
     */
    set(key, data, expireTime = cacheOptions.expireTime, autoRefresh = cacheOptions.autoRefresh, refreshCallback = null) {
      if (!key) return false;
      
      try {
        const cacheKey = `${modulePrefix}${key}`;
        const now = dayjs().valueOf();
        const expireAt = now + expireTime;
        
        const cacheData = {
          data,
          timestamp: now,
          expireTime: expireAt,
          module: moduleName
        };
        
        // 日志
        if (cacheOptions.debug) {
          console.log(`[${moduleName}] 缓存数据: ${key}，过期时间: ${dayjs(expireAt).format('YYYY-MM-DD HH:mm:ss')}`);
        }
        
        // 更新统计
        this.stats.setCount++;
        
        // 设置自动刷新
        if (autoRefresh && refreshCallback && typeof refreshCallback === 'function') {
          this._setupRefreshTimer(key, expireTime, refreshCallback);
        }
        
        return cacheHelper.set(cacheKey, cacheData);
      } catch (error) {
        console.error(`[${moduleName}] 缓存数据失败 [${key}]:`, error);
        return false;
      }
    },
    
    /**
     * 获取缓存
     * @param {String} key 缓存键
     * @param {Boolean} ignoreExpire 是否忽略过期检查
     * @return {Object|null} 缓存数据或null
     */
    get(key, ignoreExpire = false) {
      if (!key) return null;
      
      try {
        const cacheKey = `${modulePrefix}${key}`;
        const cache = cacheHelper.get(cacheKey);
        
        if (!cache) {
          // 更新统计
          this.stats.missCount++;
          
          // 日志
          if (cacheOptions.debug) {
            console.log(`[${moduleName}] 缓存未命中: ${key}`);
          }
          
          return null;
        }
        
        // 检查是否过期
        if (!ignoreExpire && cache.expireTime < dayjs().valueOf()) {
          // 已过期，清除缓存
          this.remove(key);
          
          // 更新统计
          this.stats.missCount++;
          
          // 日志
          if (cacheOptions.debug) {
            console.log(`[${moduleName}] 缓存已过期: ${key}`);
          }
          
          return null;
        }
        
        // 更新统计
        this.stats.hitCount++;
        
        // 日志
        if (cacheOptions.debug) {
          console.log(`[${moduleName}] 缓存命中: ${key}`);
        }
        
        // 返回缓存数据
        return cache.data;
      } catch (error) {
        console.error(`[${moduleName}] 获取缓存失败 [${key}]:`, error);
        return null;
      }
    },
    
    /**
     * 检查缓存是否存在且未过期
     * @param {String} key 缓存键
     * @return {Boolean} 是否存在有效缓存
     */
    has(key) {
      if (!key) return false;
      
      try {
        const cacheKey = `${modulePrefix}${key}`;
        const cache = cacheHelper.get(cacheKey);
        
        if (!cache) return false;
        
        // 检查是否过期
        return cache.expireTime >= dayjs().valueOf();
      } catch (error) {
        console.error(`[${moduleName}] 检查缓存失败 [${key}]:`, error);
        return false;
      }
    },
    
    /**
     * 删除缓存
     * @param {String} key 缓存键
     * @return {Boolean} 操作结果
     */
    remove(key) {
      if (!key) return false;
      
      try {
        const cacheKey = `${modulePrefix}${key}`;
        
        // 清除刷新定时器
        this._clearRefreshTimer(key);
        
        // 更新统计
        this.stats.removeCount++;
        
        // 日志
        if (cacheOptions.debug) {
          console.log(`[${moduleName}] 删除缓存: ${key}`);
        }
        
        return cacheHelper.remove(cacheKey);
      } catch (error) {
        console.error(`[${moduleName}] 删除缓存失败 [${key}]:`, error);
        return false;
      }
    },
    
    /**
     * 更新缓存过期时间
     * @param {String} key 缓存键
     * @param {Number} expireTime 新的过期时间（毫秒）
     * @return {Boolean} 操作结果
     */
    updateExpireTime(key, expireTime = cacheOptions.expireTime) {
      if (!key) return false;
      
      try {
        const cacheKey = `${modulePrefix}${key}`;
        const cache = cacheHelper.get(cacheKey);
        
        if (!cache) return false;
        
        const newExpireTime = dayjs().valueOf() + expireTime;
        
        // 更新缓存数据的过期时间
        cache.expireTime = newExpireTime;
        
        // 日志
        if (cacheOptions.debug) {
          console.log(`[${moduleName}] 更新缓存过期时间: ${key}, 新过期时间: ${dayjs(newExpireTime).format('YYYY-MM-DD HH:mm:ss')}`);
        }
        
        // 保存更新后的缓存
        return cacheHelper.set(cacheKey, cache);
      } catch (error) {
        console.error(`[${moduleName}] 更新缓存过期时间失败 [${key}]:`, error);
        return false;
      }
    },
    
    /**
     * 清除所有模块缓存
     * @return {Boolean} 操作结果
     */
    clearAll() {
      try {
        // 清除所有刷新定时器
        Object.keys(refreshTimers).forEach(key => {
          this._clearRefreshTimer(key);
        });
        
        // 获取所有缓存键
        const allKeys = cacheHelper.getAllKeys();
        
        // 遍历并删除模块相关的缓存
        let removed = 0;
        for (const fullKey of allKeys) {
          if (fullKey.startsWith(modulePrefix)) {
            cacheHelper.remove(fullKey);
            removed++;
          }
        }
        
        // 更新统计
        this.stats.lastCleanTime = dayjs().valueOf();
        this.stats.removeCount += removed;
        
        // 日志
        if (cacheOptions.debug) {
          console.log(`[${moduleName}] 清除了${removed}个模块缓存`);
        }
        
        return true;
      } catch (error) {
        console.error(`[${moduleName}] 清除所有缓存失败:`, error);
        return false;
      }
    },
    
    /**
     * 重置缓存统计数据
     */
    resetStats() {
      this.stats = {
        hitCount: 0,
        missCount: 0,
        setCount: 0,
        removeCount: 0,
        lastCleanTime: this.stats.lastCleanTime
      };
    },
    
    /**
     * 启动自动清理
     */
    startAutoCleanup() {
      // 清除现有定时器
      if (cleanupTimer) {
        clearInterval(cleanupTimer);
      }
      
      // 设置新定时器
      cleanupTimer = setInterval(() => {
        this._cleanupExpiredCache();
      }, cacheOptions.cleanupInterval);
      
      if (cacheOptions.debug) {
        console.log(`[${moduleName}] 启动自动清理，间隔: ${cacheOptions.cleanupInterval / 60000}分钟`);
      }
    },
    
    /**
     * 停止自动清理
     */
    stopAutoCleanup() {
      if (cleanupTimer) {
        clearInterval(cleanupTimer);
        cleanupTimer = null;
        
        if (cacheOptions.debug) {
          console.log(`[${moduleName}] 停止自动清理`);
        }
      }
    },
    
    /**
     * 获取缓存命中率
     */
    getHitRate() {
      const total = this.stats.hitCount + this.stats.missCount;
      if (total === 0) return 0;
      return (this.stats.hitCount / total * 100).toFixed(2);
    },
    
    /**
     * 设置自动刷新定时器
     * @private
     */
    _setupRefreshTimer(key, expireTime, refreshCallback) {
      // 清除已有定时器
      this._clearRefreshTimer(key);
      
      // 设置新定时器，在过期前10秒刷新
      const refreshTime = Math.max(expireTime - 10000, expireTime / 2);
      
      refreshTimers[key] = setTimeout(() => {
        this._refreshCache(key, refreshCallback);
      }, refreshTime);
      
      if (cacheOptions.debug) {
        console.log(`[${moduleName}] 设置自动刷新定时器: ${key}, ${refreshTime / 1000}秒后刷新`);
      }
    },
    
    /**
     * 清除刷新定时器
     * @private
     */
    _clearRefreshTimer(key) {
      if (refreshTimers[key]) {
        clearTimeout(refreshTimers[key]);
        delete refreshTimers[key];
      }
    },
    
    /**
     * 刷新缓存
     * @private
     */
    async _refreshCache(key, refreshCallback) {
      if (!key || !refreshCallback || typeof refreshCallback !== 'function') return false;
      
      try {
        // 执行刷新回调获取新数据
        const newData = await refreshCallback();
        
        // 日志
        if (cacheOptions.debug) {
          console.log(`[${moduleName}] 刷新缓存: ${key}`);
        }
        
        // 重新缓存数据
        return this.set(key, newData, cacheOptions.expireTime, true, refreshCallback);
      } catch (error) {
        console.error(`[${moduleName}] 刷新缓存失败 [${key}]:`, error);
        return false;
      }
    },
    
    /**
     * 清理过期缓存
     * @private
     */
    _cleanupExpiredCache() {
      const now = dayjs().valueOf();
      let cleanCount = 0;
      
      try {
        // 获取所有模块缓存键
        const allKeys = cacheHelper.getAllKeys();
        
        // 遍历过滤模块相关键
        for (const fullKey of allKeys) {
          if (fullKey.startsWith(modulePrefix)) {
            const cache = cacheHelper.get(fullKey);
            
            if (cache && cache.expireTime < now) {
              // 提取短键名
              const shortKey = fullKey.replace(modulePrefix, '');
              
              // 移除过期缓存
              this.remove(shortKey);
              cleanCount++;
            }
          }
        }
        
        if (cleanCount > 0 && cacheOptions.debug) {
          console.log(`[${moduleName}] 自动清理了${cleanCount}个过期缓存`);
        }
        
        // 更新最后清理时间
        this.stats.lastCleanTime = now;
      } catch (error) {
        console.error(`[${moduleName}] 清理过期缓存失败:`, error);
      }
    }
  };
  
  // 初始化：启动自动清理
  cacheManager.startAutoCleanup();
  
  return cacheManager;
}

export default { createCacheManager }; 